home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / Direct3D / PostProcess / PostProcess.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-28  |  78.8 KB  |  1,975 lines

  1. //--------------------------------------------------------------------------------------
  2. // File: PostProcess.cpp
  3. //
  4. // Starting point for new Direct3D applications
  5. //
  6. // Copyright (c) Microsoft Corporation. All rights reserved.
  7. //--------------------------------------------------------------------------------------
  8. #include "dxstdafx.h"
  9. #include "resource.h"
  10. #include <stdio.h>
  11.  
  12.  
  13. //#define DEBUG_VS   // Uncomment this line to debug vertex shaders 
  14. //#define DEBUG_PS   // Uncomment this line to debug pixel shaders 
  15.  
  16.  
  17. // PPCOUNT is the number of postprocess effects supported
  18. #define PPCOUNT (sizeof(g_aszFxFile) / sizeof(g_aszFxFile[0]))
  19.  
  20.  
  21. // NUM_PARAMS is the maximum number of changeable parameters supported
  22. // in an effect.
  23. #define NUM_PARAMS 2
  24.  
  25.  
  26. // RT_COUNT is the number of simultaneous render targets used in the sample.
  27. #define RT_COUNT 3
  28.  
  29.  
  30. // Name of the postprocess .fx files
  31. LPCWSTR g_aszFxFile[] =
  32. {
  33.     L"PP_ColorMonochrome.fx",
  34.     L"PP_ColorInverse.fx",
  35.     L"PP_ColorGBlurH.fx",
  36.     L"PP_ColorGBlurV.fx",
  37.     L"PP_ColorBloomH.fx",
  38.     L"PP_ColorBloomV.fx",
  39.     L"PP_ColorBrightPass.fx",
  40.     L"PP_ColorToneMap.fx",
  41.     L"PP_ColorEdgeDetect.fx",
  42.     L"PP_ColorDownFilter4.fx",
  43.     L"PP_ColorUpFilter4.fx",
  44.     L"PP_ColorCombine.fx",
  45.     L"PP_ColorCombine4.fx",
  46.     L"PP_NormalEdgeDetect.fx",
  47.     L"PP_DofCombine.fx",
  48.     L"PP_NormalMap.fx",
  49.     L"PP_PositionMap.fx",
  50. };
  51.  
  52.  
  53. // Description of each postprocess supported
  54. LPCWSTR g_aszPpDesc[] =
  55. {
  56.     L"[Color] Monochrome",
  57.     L"[Color] Inversion",
  58.     L"[Color] Gaussian Blur Horizontal",
  59.     L"[Color] Gaussian Blur Vertical",
  60.     L"[Color] Bloom Horizontal",
  61.     L"[Color] Bloom Vertical",
  62.     L"[Color] Bright Pass",
  63.     L"[Color] Tone Mapping",
  64.     L"[Color] Edge Detection",
  65.     L"[Color] Down Filter 4x",
  66.     L"[Color] Up Filter 4x",
  67.     L"[Color] Combine",
  68.     L"[Color] Combine 4x",
  69.     L"[Normal] Edge Detection",
  70.     L"DOF Combine",
  71.     L"Normal Map",
  72.     L"Position Map",
  73. };
  74.  
  75.  
  76. //--------------------------------------------------------------------------------------
  77. // This is the vertex format used for the meshes.
  78. struct MESHVERT
  79. {
  80.     float x, y, z;      // Position
  81.     float nx, ny, nz;   // Normal
  82.     float tu, tv;       // Texcoord
  83.  
  84.     const static D3DVERTEXELEMENT9 Decl[4];
  85. };
  86.  
  87. const D3DVERTEXELEMENT9 MESHVERT::Decl[] =
  88. {
  89.     { 0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
  90.     { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   0 },
  91.     { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
  92.     D3DDECL_END()
  93. };
  94.  
  95.  
  96. //--------------------------------------------------------------------------------------
  97. // This is the vertex format used for the skybox.
  98. struct SKYBOXVERT
  99. {
  100.     float x, y, z;      // Position
  101.     D3DXVECTOR3 tex;    // Texcoord
  102.  
  103.     const static D3DVERTEXELEMENT9 Decl[3];
  104. };
  105.  
  106. const D3DVERTEXELEMENT9 SKYBOXVERT::Decl[] =
  107. {
  108.     { 0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
  109.     { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
  110.     D3DDECL_END()
  111. };
  112.  
  113.  
  114. //--------------------------------------------------------------------------------------
  115. // This is the vertex format used with the quad during post-process.
  116. struct PPVERT
  117. {
  118.     float x, y, z, rhw;
  119.     float tu, tv;       // Texcoord for post-process source
  120.     float tu2, tv2;     // Texcoord for the original scene
  121.  
  122.     const static D3DVERTEXELEMENT9 Decl[4];
  123. };
  124.  
  125. // Vertex declaration for post-processing
  126. const D3DVERTEXELEMENT9 PPVERT::Decl[4] =
  127. {
  128.     { 0, 0,  D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 0 },
  129.     { 0, 16, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,  0 },
  130.     { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,  1 },
  131.     D3DDECL_END()
  132. };
  133.  
  134.  
  135. //--------------------------------------------------------------------------------------
  136. // struct CPostProcess
  137. // A struct that encapsulates aspects of a render target postprocess
  138. // technique.
  139. //--------------------------------------------------------------------------------------
  140. struct CPostProcess
  141. {
  142.     LPD3DXEFFECT m_pEffect;              // Effect object for this technique
  143.     D3DXHANDLE   m_hTPostProcess;        // PostProcess technique handle
  144.     int          m_nRenderTarget;        // Render target channel this PP outputs
  145.     D3DXHANDLE   m_hTexSource[4];        // Handle to the post-process source textures
  146.     D3DXHANDLE   m_hTexScene[4];         // Handle to the saved scene texture
  147.     bool         m_bWrite[4];            // Indicates whether the post-process technique
  148.                                          //   outputs data for this render target.
  149.     WCHAR        m_awszParamName
  150.                  [NUM_PARAMS][MAX_PATH]; // Names of changeable parameters
  151.     WCHAR        m_awszParamDesc
  152.                  [NUM_PARAMS][MAX_PATH]; // Description of parameters
  153.     D3DXHANDLE   m_ahParam[NUM_PARAMS];  // Handles to the changeable parameters
  154.     int          m_anParamSize[NUM_PARAMS];// Size of the parameter. Indicates
  155.                                            // how many components of float4
  156.                                            // are used.
  157.     D3DXVECTOR4  m_avParamDef[NUM_PARAMS]; // Parameter default
  158.  
  159. public:
  160.     CPostProcess() :
  161.         m_pEffect(NULL), m_hTPostProcess(NULL),
  162.         m_nRenderTarget(0)
  163.     {
  164.         ZeroMemory( m_hTexSource, sizeof(m_hTexSource) );
  165.         ZeroMemory( m_hTexScene, sizeof(m_hTexScene) );
  166.         ZeroMemory( m_bWrite, sizeof(m_bWrite) );
  167.         ZeroMemory( m_ahParam, sizeof(m_ahParam) );
  168.         ZeroMemory( m_awszParamName, sizeof(m_awszParamName) );
  169.         ZeroMemory( m_awszParamDesc, sizeof(m_awszParamDesc) );
  170.         ZeroMemory( m_anParamSize, sizeof(m_anParamSize) );
  171.         ZeroMemory( m_avParamDef, sizeof(m_avParamDef) );
  172.     }
  173.     ~CPostProcess() { Cleanup(); }
  174.     HRESULT Init( LPDIRECT3DDEVICE9 pDev, DWORD dwShaderFlags, LPCWSTR wszName )
  175.     {
  176.         HRESULT hr;
  177.         WCHAR wszPath[MAX_PATH];
  178.  
  179.         if( FAILED( hr = DXUTFindDXSDKMediaFileCch( wszPath, MAX_PATH, wszName ) ) )
  180.             return hr;
  181.         hr = D3DXCreateEffectFromFile( pDev,
  182.                                        wszPath,
  183.                                        NULL,
  184.                                        NULL,
  185.                                        dwShaderFlags,
  186.                                        NULL,
  187.                                        &m_pEffect,
  188.                                        NULL );
  189.         if( FAILED( hr ) )
  190.             return hr;
  191.  
  192.         // Get the PostProcess technique handle
  193.         m_hTPostProcess = m_pEffect->GetTechniqueByName( "PostProcess" );
  194.  
  195.         // Obtain the handles to all texture objects in the effect
  196.         m_hTexScene[0] = m_pEffect->GetParameterByName( NULL, "g_txSceneColor" );
  197.         m_hTexScene[1] = m_pEffect->GetParameterByName( NULL, "g_txSceneNormal" );
  198.         m_hTexScene[2] = m_pEffect->GetParameterByName( NULL, "g_txScenePosition" );
  199.         m_hTexScene[3] = m_pEffect->GetParameterByName( NULL, "g_txSceneVelocity" );
  200.         m_hTexSource[0] = m_pEffect->GetParameterByName( NULL, "g_txSrcColor" );
  201.         m_hTexSource[1] = m_pEffect->GetParameterByName( NULL, "g_txSrcNormal" );
  202.         m_hTexSource[2] = m_pEffect->GetParameterByName( NULL, "g_txSrcPosition" );
  203.         m_hTexSource[3] = m_pEffect->GetParameterByName( NULL, "g_txSrcVelocity" );
  204.  
  205.         // Find out what render targets the technique writes to.
  206.         D3DXTECHNIQUE_DESC techdesc;
  207.         if( FAILED( m_pEffect->GetTechniqueDesc( m_hTPostProcess, &techdesc ) ) )
  208.             return D3DERR_INVALIDCALL;
  209.  
  210.         for( DWORD i = 0; i < techdesc.Passes; ++i )
  211.         {
  212.             D3DXPASS_DESC passdesc;
  213.             if( SUCCEEDED( m_pEffect->GetPassDesc( m_pEffect->GetPass( m_hTPostProcess, i ), &passdesc ) ) )
  214.             {
  215.                 D3DXSEMANTIC aSem[MAXD3DDECLLENGTH];
  216.                 UINT uCount;
  217.                 if( SUCCEEDED( D3DXGetShaderOutputSemantics( passdesc.pPixelShaderFunction, aSem, &uCount ) ) )
  218.                 {
  219.                     // Semantics received. Now examine the content and
  220.                     // find out which render target this technique
  221.                     // writes to.
  222.                     while( uCount-- )
  223.                     {
  224.                         if( D3DDECLUSAGE_COLOR == aSem[uCount].Usage &&
  225.                               RT_COUNT > aSem[uCount].UsageIndex )
  226.                             m_bWrite[uCount] = true;
  227.                     }
  228.                 }
  229.             }
  230.         }
  231.  
  232.         // Obtain the render target channel
  233.         D3DXHANDLE hAnno;
  234.         hAnno = m_pEffect->GetAnnotationByName( m_hTPostProcess, "nRenderTarget" );
  235.         if( hAnno )
  236.             m_pEffect->GetInt( hAnno, &m_nRenderTarget );
  237.  
  238.         // Obtain the handles to the changeable parameters, if any.
  239.         for( int i = 0; i < NUM_PARAMS; ++i )
  240.         {
  241.             char szName[32];
  242.  
  243.             sprintf( szName, "Parameter%d", i );
  244.             hAnno = m_pEffect->GetAnnotationByName( m_hTPostProcess, szName );
  245.             LPCSTR szParamName;
  246.             if( hAnno &&
  247.                 SUCCEEDED( m_pEffect->GetString( hAnno, &szParamName ) ) )
  248.             {
  249.                 m_ahParam[i] = m_pEffect->GetParameterByName( NULL, szParamName );
  250.                 MultiByteToWideChar( CP_ACP, 0, szParamName, -1, m_awszParamName[i], MAX_PATH );
  251.             }
  252.  
  253.             // Get the parameter description
  254.             sprintf( szName, "Parameter%dDesc", i );
  255.             hAnno = m_pEffect->GetAnnotationByName( m_hTPostProcess, szName );
  256.             if( hAnno &&
  257.                 SUCCEEDED( m_pEffect->GetString( hAnno, &szParamName ) ) )
  258.             {
  259.                 MultiByteToWideChar( CP_ACP, 0, szParamName, -1, m_awszParamDesc[i], MAX_PATH );
  260.             }
  261.  
  262.             // Get the parameter size
  263.             sprintf( szName, "Parameter%dSize", i );
  264.             hAnno = m_pEffect->GetAnnotationByName( m_hTPostProcess, szName );
  265.             if( hAnno )
  266.                 m_pEffect->GetInt( hAnno, &m_anParamSize[i] );
  267.  
  268.             // Get the parameter default
  269.             sprintf( szName, "Parameter%dDef", i );
  270.             hAnno = m_pEffect->GetAnnotationByName( m_hTPostProcess, szName );
  271.             if( hAnno )
  272.                 m_pEffect->GetVector( hAnno, &m_avParamDef[i] );
  273.         }
  274.  
  275.         return S_OK;
  276.     }
  277.     void Cleanup()
  278.     {
  279.         SAFE_RELEASE( m_pEffect );
  280.     }
  281.     HRESULT OnLostDevice()
  282.     {
  283.         assert( m_pEffect );
  284.         m_pEffect->OnLostDevice();
  285.         return S_OK;
  286.     }
  287.     HRESULT OnResetDevice( DWORD dwWidth, DWORD dwHeight )
  288.     {
  289.         assert( m_pEffect );
  290.         m_pEffect->OnResetDevice();
  291.  
  292.         // If one or more kernel exists, convert kernel from
  293.         // pixel space to texel space.
  294.  
  295.         // First check for kernels.  Kernels are identified by
  296.         // having a string annotation of name "ConvertPixelsToTexels"
  297.         D3DXHANDLE hParamToConvert;
  298.         D3DXHANDLE hAnnotation;
  299.         UINT uParamIndex = 0;
  300.         // If a top-level parameter has the "ConvertPixelsToTexels" annotation,
  301.         // do the conversion.
  302.         while( NULL != ( hParamToConvert = m_pEffect->GetParameter( NULL, uParamIndex++ ) ) )
  303.         {
  304.             if( NULL != ( hAnnotation = m_pEffect->GetAnnotationByName( hParamToConvert, "ConvertPixelsToTexels" ) ) )
  305.             {
  306.                 LPCSTR szSource;
  307.                 m_pEffect->GetString( hAnnotation, &szSource );
  308.                 D3DXHANDLE hConvertSource = m_pEffect->GetParameterByName( NULL, szSource );
  309.  
  310.                 if( hConvertSource )
  311.                 {
  312.                     // Kernel source exists. Proceed.
  313.                     // Retrieve the kernel size
  314.                     D3DXPARAMETER_DESC desc;
  315.                     m_pEffect->GetParameterDesc( hConvertSource, &desc );
  316.                     // Each element has 2 floats
  317.                     DWORD cKernel = desc.Bytes / (2 * sizeof(float));
  318.                     D3DXVECTOR4 *pvKernel = new D3DXVECTOR4[cKernel];
  319.                     if( !pvKernel )
  320.                         return E_OUTOFMEMORY;
  321.                     m_pEffect->GetVectorArray( hConvertSource, pvKernel, cKernel );
  322.                     // Convert
  323.                     for( DWORD i = 0; i < cKernel; ++i )
  324.                     {
  325.                         pvKernel[i].x = pvKernel[i].x / dwWidth;
  326.                         pvKernel[i].y = pvKernel[i].y / dwHeight;
  327.                     }
  328.                     // Copy back
  329.                     m_pEffect->SetVectorArray( hParamToConvert, pvKernel, cKernel );
  330.  
  331.                     delete[] pvKernel;
  332.                 }
  333.             }
  334.         }
  335.  
  336.         return S_OK;
  337.     }
  338. };
  339.  
  340.  
  341. //--------------------------------------------------------------------------------------
  342. // struct CPProcInstance
  343. // A class that represents an instance of a post-process to be applied
  344. // to the scene.
  345. //--------------------------------------------------------------------------------------
  346. struct CPProcInstance
  347. {
  348.     D3DXVECTOR4 m_avParam[NUM_PARAMS];
  349.     int m_nFxIndex;
  350.  
  351. public:
  352.     CPProcInstance() :
  353.         m_nFxIndex(-1)
  354.     {
  355.         ZeroMemory( m_avParam, sizeof( m_avParam ) );
  356.     }
  357. };
  358.  
  359.  
  360. struct CRenderTargetChain
  361. {
  362.     int m_nNext;
  363.     bool m_bFirstRender;
  364.     LPDIRECT3DTEXTURE9 m_pRenderTarget[2];
  365.  
  366. public:
  367.     CRenderTargetChain() :
  368.         m_nNext( 0 ), m_bFirstRender( true )
  369.     {
  370.         ZeroMemory( m_pRenderTarget, sizeof(m_pRenderTarget) );
  371.     }
  372.  
  373.     ~CRenderTargetChain()
  374.     {
  375.         Cleanup();
  376.     }
  377.  
  378.     void Init( LPDIRECT3DTEXTURE9 *pRT )
  379.     {
  380.         for( int i = 0; i < 2; ++i )
  381.         {
  382.             m_pRenderTarget[i] = pRT[i];
  383.             m_pRenderTarget[i]->AddRef();
  384.         }
  385.     }
  386.  
  387.     void Cleanup()
  388.     {
  389.         SAFE_RELEASE( m_pRenderTarget[0] );
  390.         SAFE_RELEASE( m_pRenderTarget[1] );
  391.     }
  392.  
  393.     void Flip() { m_nNext = 1 - m_nNext; };
  394.  
  395.     LPDIRECT3DTEXTURE9 GetPrevTarget() { return m_pRenderTarget[1 - m_nNext]; }
  396.     LPDIRECT3DTEXTURE9 GetPrevSource() { return m_pRenderTarget[m_nNext]; }
  397.     LPDIRECT3DTEXTURE9 GetNextTarget() { return m_pRenderTarget[m_nNext]; }
  398.     LPDIRECT3DTEXTURE9 GetNextSource() { return m_pRenderTarget[1 - m_nNext]; }
  399. };
  400.  
  401.  
  402. // An CRenderTargetSet object dictates what render targets
  403. // to use in a pass of scene rendering.
  404. struct CRenderTargetSet
  405. {
  406.     IDirect3DSurface9* pRT[RT_COUNT];
  407. };
  408.  
  409.  
  410. //--------------------------------------------------------------------------------------
  411. // Global variables
  412. //--------------------------------------------------------------------------------------
  413. ID3DXFont*              g_pFont = NULL;          // Font for drawing text
  414. ID3DXSprite*            g_pTextSprite = NULL;    // Sprite for batching draw text calls
  415. ID3DXEffect*            g_pEffect = NULL;        // D3DX effect interface
  416. CModelViewerCamera      g_Camera;                // A model viewing camera
  417. bool                    g_bShowHelp = true;      // If true, it renders the UI control text
  418. CDXUTDialog             g_HUD;                   // dialog for standard controls
  419. CDXUTDialog             g_SampleUI;              // dialog for sample specific controls
  420. IDirect3DCubeTexture9*  g_pEnvTex;               // Texture for environment mapping
  421. IDirect3DVertexDeclaration9* g_pVertDecl = NULL; // Vertex decl for scene rendering
  422. IDirect3DVertexDeclaration9* g_pSkyBoxDecl=NULL; // Vertex decl for Skybox rendering
  423. IDirect3DVertexDeclaration9* g_pVertDeclPP=NULL; // Vertex decl for post-processing
  424. D3DXMATRIXA16           g_mMeshWorld;            // World matrix (xlate and scale) for the mesh
  425. int                     g_nScene = 0;            // Indicates the scene # to render
  426. CPostProcess            g_aPostProcess[PPCOUNT]; // Effect object for postprocesses
  427. D3DXHANDLE              g_hTRenderScene;         // Handle to RenderScene technique
  428. D3DXHANDLE              g_hTRenderEnvMapScene;   // Handle to RenderEnvMapScene technique
  429. D3DXHANDLE              g_hTRenderNoLight;       // Handle to RenderNoLight technique
  430. D3DXHANDLE              g_hTRenderSkyBox;        // Handle to RenderSkyBox technique
  431. CDXUTMesh               g_SceneMesh[2];          // Mesh objects in the scene
  432. CDXUTMesh               g_Skybox;                // Skybox mesh
  433. D3DFORMAT               g_TexFormat;             // Render target texture format
  434. IDirect3DTexture9*      g_pSceneSave[RT_COUNT];  // To save original scene image before postprocess
  435. CRenderTargetChain      g_RTChain[RT_COUNT];     // Render target chain (4 used in sample)
  436. bool                    g_bEnablePostProc = true;// Whether or not to enable post-processing
  437.  
  438. int                     g_nPasses = 0;           // Number of passes required to render scene
  439. int                     g_nRtUsed = 0;           // Number of simultaneous RT used to render scene
  440. CRenderTargetSet        g_aRtTable[RT_COUNT];    // Table of which RT to use for all passes
  441.  
  442.  
  443. //--------------------------------------------------------------------------------------
  444. // UI control IDs
  445. //--------------------------------------------------------------------------------------
  446. #define IDC_TOGGLEFULLSCREEN    1
  447. #define IDC_TOGGLEREF           3
  448. #define IDC_CHANGEDEVICE        4
  449. #define IDC_SELECTSCENE         5
  450. #define IDC_AVAILABLELIST       6
  451. #define IDC_ACTIVELIST          7
  452. #define IDC_AVAILABLELISTLABEL  8
  453. #define IDC_ACTIVELISTLABEL     9
  454. #define IDC_PARAM0NAME          10
  455. #define IDC_PARAM1NAME          11
  456. #define IDC_PARAM0              12
  457. #define IDC_PARAM1              13
  458. #define IDC_MOVEUP              14
  459. #define IDC_MOVEDOWN            15
  460. #define IDC_CLEAR               16
  461. #define IDC_ENABLEPP            17
  462. #define IDC_PRESETLABEL         18
  463. #define IDC_PREBLUR             19
  464. #define IDC_PREBLOOM            20
  465. #define IDC_PREDOF              21
  466. #define IDC_PREEDGE             22
  467.  
  468.  
  469. //--------------------------------------------------------------------------------------
  470. // Forward declarations 
  471. //--------------------------------------------------------------------------------------
  472. bool    CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed );
  473. void    CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps );
  474. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  475. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  476. void    CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  477. void    CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  478. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing );
  479. void    CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown  );
  480. void    CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl );
  481. void    CALLBACK OnLostDevice();
  482. void    CALLBACK OnDestroyDevice();
  483.  
  484. void    InitApp();
  485. HRESULT LoadMesh( IDirect3DDevice9* pd3dDevice, WCHAR* strFileName, ID3DXMesh** ppMesh );
  486. void    RenderText();
  487. HRESULT PerformSinglePostProcess( CPostProcess &PP, CPProcInstance &Inst, LPDIRECT3DVERTEXBUFFER9 pVB, PPVERT *aQuad, float &fExtentX, float &fExtentY );
  488. HRESULT PerformPostProcess( IDirect3DDevice9 *pd3dDevice );
  489. HRESULT ComputeMeshWorldMatrix( LPD3DXMESH pMesh );
  490.  
  491.  
  492. //--------------------------------------------------------------------------------------
  493. // Empty the active effect list except the last (blank) item.
  494. void ClearActiveList()
  495. {
  496.     // Clear all items in the active list except the last one.
  497.  
  498.     CDXUTListBox *pListBox = g_SampleUI.GetListBox( IDC_ACTIVELIST );
  499.     if( !pListBox )
  500.         return;
  501.  
  502.     int i = (int)pListBox->GetSize() - 1;
  503.     while( --i >= 0 )
  504.     {
  505.         DXUTListBoxItem *pItem = pListBox->GetItem( 0 );
  506.         delete pItem->pData;
  507.         pListBox->RemoveItem( 0 );
  508.     }
  509. }
  510.  
  511.  
  512. //--------------------------------------------------------------------------------------
  513. // Entry point to the program. Initializes everything and goes into a message processing 
  514. // loop. Idle time is used to render the scene.
  515. //--------------------------------------------------------------------------------------
  516. INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
  517. {
  518.     // Set the callback functions. These functions allow the sample framework to notify
  519.     // the application about device changes, user input, and windows messages.  The 
  520.     // callbacks are optional so you need only set callbacks for events you're interested 
  521.     // in. However, if you don't handle the device reset/lost callbacks then the sample 
  522.     // framework won't be able to reset your device since the application must first 
  523.     // release all device resources before resetting.  Likewise, if you don't handle the 
  524.     // device created/destroyed callbacks then the sample framework won't be able to 
  525.     // recreate your device resources.
  526.     DXUTSetCallbackDeviceCreated( OnCreateDevice );
  527.     DXUTSetCallbackDeviceReset( OnResetDevice );
  528.     DXUTSetCallbackDeviceLost( OnLostDevice );
  529.     DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
  530.     DXUTSetCallbackMsgProc( MsgProc );
  531.     DXUTSetCallbackKeyboard( KeyboardProc );
  532.     DXUTSetCallbackFrameRender( OnFrameRender );
  533.     DXUTSetCallbackFrameMove( OnFrameMove );
  534.  
  535.     // Show the cursor and clip it when in full screen
  536.     DXUTSetCursorSettings( true, true );
  537.  
  538.     InitApp();
  539.  
  540.     // Initialize the sample framework and create the desired Win32 window and Direct3D 
  541.     // device for the application. Calling each of these functions is optional, but they
  542.     // allow you to set several options which control the behavior of the framework.
  543.     DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
  544.     DXUTCreateWindow( L"PostProcess" );
  545.     DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );
  546.  
  547.     // Pass control to the sample framework for handling the message pump and 
  548.     // dispatching render calls. The sample framework will call your FrameMove 
  549.     // and FrameRender callback when there is idle time between handling window messages.
  550.     DXUTMainLoop();
  551.  
  552.     // Perform any application-level cleanup here. Direct3D device resources are released within the
  553.     // appropriate callback functions and therefore don't require any cleanup code here.
  554.     ClearActiveList();
  555.  
  556.     return DXUTGetExitCode();
  557. }
  558.  
  559.  
  560. //--------------------------------------------------------------------------------------
  561. // Initialize the app 
  562. //--------------------------------------------------------------------------------------
  563. void InitApp()
  564. {
  565.     // Initialize dialogs
  566.     g_HUD.SetCallback( OnGUIEvent ); int iY = 0; 
  567.     g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 0, iY, 125, 22 );
  568.     g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 0, iY += 24, 125, 22 );
  569.     g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 0, iY += 24, 125, 22 );
  570.  
  571.     g_SampleUI.SetCallback( OnGUIEvent ); iY = 5;
  572.     g_SampleUI.EnableCaption( true );
  573.     g_SampleUI.SetCaptionText( L"Effect Manager" );
  574.     g_SampleUI.SetBackgroundColors( D3DCOLOR_ARGB( 100, 255, 255, 255 ) );
  575.  
  576.     // Initialize sample-specific UI controls
  577.     g_SampleUI.AddStatic( IDC_AVAILABLELISTLABEL, L"Available effects (Dbl click inserts effect):", 10, iY, 210, 16 );
  578.     g_SampleUI.GetStatic( IDC_AVAILABLELISTLABEL )->GetElement( 0 )->dwTextFormat = DT_LEFT|DT_TOP;
  579.     CDXUTListBox *pListBox;
  580.     g_SampleUI.AddListBox( IDC_AVAILABLELIST, 10, iY += 18, 200, 82, 0, &pListBox );
  581.     if( pListBox )
  582.     {
  583.         // Populate ListBox items
  584.         for( int i = 0; i < PPCOUNT; ++i )
  585.             pListBox->AddItem( g_aszPpDesc[i], (LPVOID)(size_t)i );
  586.     }
  587.     g_SampleUI.AddStatic( IDC_ACTIVELISTLABEL, L"Active effects (Dbl click removes effect):", 10, iY += 87, 210, 16 );
  588.     g_SampleUI.GetStatic( IDC_ACTIVELISTLABEL )->GetElement( 0 )->dwTextFormat = DT_LEFT|DT_TOP;
  589.     g_SampleUI.AddListBox( IDC_ACTIVELIST, 10, iY += 18, 200, 82, 0, &pListBox );
  590.     if( pListBox )
  591.     {
  592.         // Add a blank entry for users to add effect to the end of list.
  593.         pListBox->AddItem( L"", NULL );
  594.     }
  595.     g_SampleUI.AddButton( IDC_MOVEUP, L"Move Up", 0, iY += 92, 70, 22 );
  596.     g_SampleUI.AddButton( IDC_MOVEDOWN, L"Move Down", 72, iY, 75, 22 );
  597.     g_SampleUI.AddButton( IDC_CLEAR, L"Clear All", 149, iY, 65, 22 );
  598.     g_SampleUI.AddStatic( IDC_PARAM0NAME, L"Select an active effect to set its parameter.", 5, iY += 24, 215, 15 );
  599.     g_SampleUI.GetStatic( IDC_PARAM0NAME )->GetElement( 0 )->dwTextFormat = DT_LEFT|DT_TOP;
  600.     CDXUTEditBox *pEditBox;
  601.     g_SampleUI.AddEditBox( IDC_PARAM0, L"", 5, iY += 15, 210, 20, false, &pEditBox );
  602.     if( pEditBox )
  603.     {
  604.         pEditBox->SetBorderWidth( 1 );
  605.         pEditBox->SetSpacing( 2 );
  606.     }
  607.     g_SampleUI.AddStatic( IDC_PARAM1NAME, L"Select an active effect to set its parameter.", 5, iY += 20, 215, 15 );
  608.     g_SampleUI.GetStatic( IDC_PARAM1NAME )->GetElement( 0 )->dwTextFormat = DT_LEFT|DT_TOP;
  609.     g_SampleUI.AddEditBox( IDC_PARAM1, L"", 5, iY += 15, 210, 20, false, &pEditBox );
  610.     if( pEditBox )
  611.     {
  612.         pEditBox->SetBorderWidth( 1 );
  613.         pEditBox->SetSpacing( 2 );
  614.     }
  615.  
  616.     // Disable the edit boxes and 2nd static control by default.
  617.     g_SampleUI.GetControl( IDC_PARAM0 )->SetEnabled( false );
  618.     g_SampleUI.GetControl( IDC_PARAM0 )->SetVisible( false );
  619.     g_SampleUI.GetControl( IDC_PARAM1 )->SetEnabled( false );
  620.     g_SampleUI.GetControl( IDC_PARAM1 )->SetVisible( false );
  621.     g_SampleUI.GetControl( IDC_PARAM1NAME )->SetEnabled( false );
  622.     g_SampleUI.GetControl( IDC_PARAM1NAME )->SetVisible( false );
  623.  
  624.     g_SampleUI.AddCheckBox( IDC_ENABLEPP, L"(E)nable post-processing", 5, iY += 25, 200, 24, true, L'E' );
  625.  
  626.     CDXUTComboBox *pComboBox;
  627.     g_SampleUI.AddComboBox( IDC_SELECTSCENE, 5, iY += 25, 210, 24, L'C', false, &pComboBox );
  628.     if( pComboBox )
  629.     {
  630.         pComboBox->AddItem( L"(C)urrent Mesh: Dwarf", (LPVOID)0 );
  631.         pComboBox->AddItem( L"(C)urrent Mesh: Skull", (LPVOID)1 );
  632.     }
  633.  
  634.     g_SampleUI.AddStatic( IDC_PRESETLABEL, L"Predefined post-process combinations:", 5, iY += 28, 210, 22 );
  635.     g_SampleUI.GetControl( IDC_PRESETLABEL )->GetElement( 0 )->dwTextFormat = DT_LEFT|DT_TOP;
  636.     g_SampleUI.AddButton( IDC_PREBLUR, L"Blur", 5, iY += 22, 100, 22 );
  637.     g_SampleUI.AddButton( IDC_PREBLOOM, L"Bloom", 115, iY, 100, 22 );
  638.     g_SampleUI.AddButton( IDC_PREDOF, L"Depth of Field", 5, iY += 24, 100, 22 );
  639.     g_SampleUI.AddButton( IDC_PREEDGE, L"Edge Glow", 115, iY, 100, 22 );
  640.  
  641.     // Initialize camera parameters
  642.     g_Camera.SetModelCenter( D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) );
  643.     g_Camera.SetRadius( 2.8f );
  644.     g_Camera.SetEnablePositionMovement( false );
  645. }
  646.  
  647.  
  648. //--------------------------------------------------------------------------------------
  649. // Compute the translate and scale transform for the current mesh.
  650. HRESULT ComputeMeshWorldMatrix( LPD3DXMESH pMesh )
  651. {
  652.     LPDIRECT3DVERTEXBUFFER9 pVB;
  653.     if( FAILED( pMesh->GetVertexBuffer( &pVB ) ) )
  654.         return E_FAIL;
  655.  
  656.     LPVOID pVBData;
  657.     if( SUCCEEDED( pVB->Lock( 0, 0, &pVBData, D3DLOCK_READONLY ) ) )
  658.     {
  659.         D3DXVECTOR3 vCtr;
  660.         float fRadius;
  661.         D3DXComputeBoundingSphere( (D3DXVECTOR3*)pVBData, pMesh->GetNumVertices(),
  662.                                    D3DXGetFVFVertexSize( pMesh->GetFVF() ),
  663.                                    &vCtr, &fRadius );
  664.  
  665.         D3DXMatrixTranslation( &g_mMeshWorld, -vCtr.x, -vCtr.y, -vCtr.z );
  666.         D3DXMATRIXA16 m;
  667.         D3DXMatrixScaling( &m, 1/fRadius, 1/fRadius, 1/fRadius );
  668.         D3DXMatrixMultiply( &g_mMeshWorld, &g_mMeshWorld, &m );
  669.  
  670.         pVB->Unlock();
  671.     }
  672.  
  673.     SAFE_RELEASE( pVB );
  674.  
  675.     return S_OK;
  676. }
  677.  
  678.  
  679. //--------------------------------------------------------------------------------------
  680. // Called during device initialization, this code checks the device for some 
  681. // minimum set of capabilities, and rejects those that don't pass by returning false.
  682. //--------------------------------------------------------------------------------------
  683. bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, 
  684.                                   D3DFORMAT BackBufferFormat, bool bWindowed )
  685. {
  686.     // Skip backbuffer formats that don't support alpha blending
  687.     IDirect3D9* pD3D = DXUTGetD3DObject(); 
  688.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  689.                     AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, 
  690.                     D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
  691.         return false;
  692.  
  693.     // Check 32 bit integer format support
  694.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  695.                                          AdapterFormat, D3DUSAGE_RENDERTARGET,
  696.                                          D3DRTYPE_CUBETEXTURE, D3DFMT_A8R8G8B8 ) ) )
  697.         return false;
  698.  
  699.     // Must support pixel shader 2.0
  700.     if( pCaps->PixelShaderVersion < D3DPS_VERSION( 2, 0 ) )
  701.         return false;
  702.  
  703.     return true;
  704. }
  705.  
  706.  
  707. //--------------------------------------------------------------------------------------
  708. // This callback function is called immediately before a device is created to allow the 
  709. // application to modify the device settings. The supplied pDeviceSettings parameter 
  710. // contains the settings that the framework has selected for the new device, and the 
  711. // application can make any desired changes directly to this structure.  Note however that 
  712. // the sample framework will not correct invalid device settings so care must be taken 
  713. // to return valid device settings, otherwise IDirect3D9::CreateDevice() will fail.  
  714. //--------------------------------------------------------------------------------------
  715. void CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps )
  716. {
  717.     // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW 
  718.     // then switch to SWVP.
  719.     if( (pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 ||
  720.          pCaps->VertexShaderVersion < D3DVS_VERSION(1,1) )
  721.     {
  722.         pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  723.     }
  724.     else
  725.     {
  726.         pDeviceSettings->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  727.     }
  728.  
  729.     // This application is designed to work on a pure device by not using 
  730.     // IDirect3D9::Get*() methods, so create a pure device if supported and using HWVP.
  731.     if ((pCaps->DevCaps & D3DDEVCAPS_PUREDEVICE) != 0 && 
  732.         (pDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0 )
  733.         pDeviceSettings->BehaviorFlags |= D3DCREATE_PUREDEVICE;
  734.  
  735.     // Debugging vertex shaders requires either REF or software vertex processing 
  736.     // and debugging pixel shaders requires REF.  
  737. #ifdef DEBUG_VS
  738.     if( pDeviceSettings->DeviceType != D3DDEVTYPE_REF )
  739.     {
  740.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
  741.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_PUREDEVICE;                            
  742.         pDeviceSettings->BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  743.     }
  744. #endif
  745. #ifdef DEBUG_PS
  746.     pDeviceSettings->DeviceType = D3DDEVTYPE_REF;
  747. #endif
  748. }
  749.  
  750.  
  751. //--------------------------------------------------------------------------------------
  752. // This callback function will be called immediately after the Direct3D device has been 
  753. // created, which will happen during application initialization and windowed/full screen 
  754. // toggles. This is the best location to create D3DPOOL_MANAGED resources since these 
  755. // resources need to be reloaded whenever the device is destroyed. Resources created  
  756. // here should be released in the OnDestroyDevice callback. 
  757. //--------------------------------------------------------------------------------------
  758. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  759. {
  760.     HRESULT hr;
  761.  
  762.     // Query multiple RT setting and set the num of passes required
  763.     D3DCAPS9 Caps;
  764.     pd3dDevice->GetDeviceCaps( &Caps );
  765.     if( Caps.NumSimultaneousRTs > 2 )
  766.     {
  767.         // One pass of 3 RTs
  768.         g_nPasses = 1;
  769.         g_nRtUsed = 3;
  770.     }
  771.     else
  772.     if( Caps.NumSimultaneousRTs > 1 )
  773.     {
  774.         // Two passes of 2 RTs. The 2nd pass uses only one.
  775.         g_nPasses = 2;
  776.         g_nRtUsed = 2;
  777.     }
  778.     else
  779.     {
  780.         // Three passes of single RT.
  781.         g_nPasses = 3;
  782.         g_nRtUsed = 1;
  783.     }
  784.  
  785.     // Determine which of D3DFMT_A16B16G16R16F or D3DFMT_A8R8G8B8
  786.     // to use for scene-rendering RTs.
  787.     IDirect3D9* pD3D;
  788.     pd3dDevice->GetDirect3D( &pD3D );
  789.     D3DDISPLAYMODE DisplayMode;
  790.     pd3dDevice->GetDisplayMode( 0, &DisplayMode );
  791.  
  792.     if( FAILED( pD3D->CheckDeviceFormat( Caps.AdapterOrdinal, Caps.DeviceType,
  793.                     DisplayMode.Format, D3DUSAGE_RENDERTARGET, 
  794.                     D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F ) ) )
  795.         g_TexFormat = D3DFMT_A8R8G8B8;
  796.     else
  797.         g_TexFormat = D3DFMT_A16B16G16R16F;
  798.  
  799.     SAFE_RELEASE( pD3D );
  800.  
  801.     // Initialize the font
  802.     V_RETURN( D3DXCreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, 
  803.                          OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
  804.                          L"Arial", &g_pFont ) );
  805.  
  806.     // Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the 
  807.     // shader debugger. Debugging vertex shaders requires either REF or software vertex 
  808.     // processing, and debugging pixel shaders requires REF.  The 
  809.     // D3DXSHADER_FORCE_*_SOFTWARE_NOOPT flag improves the debug experience in the 
  810.     // shader debugger.  It enables source level debugging, prevents instruction 
  811.     // reordering, prevents dead code elimination, and forces the compiler to compile 
  812.     // against the next higher available software target, which ensures that the 
  813.     // unoptimized shaders do not exceed the shader model limitations.  Setting these 
  814.     // flags will cause slower rendering since the shaders will be unoptimized and 
  815.     // forced into software.  See the DirectX documentation for more information about 
  816.     // using the shader debugger.
  817.     DWORD dwShaderFlags = 0;
  818.     #ifdef DEBUG_VS
  819.         dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
  820.     #endif
  821.     #ifdef DEBUG_PS
  822.         dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
  823.     #endif
  824.  
  825.     // Read the D3DX effect file
  826.     WCHAR str[MAX_PATH];
  827.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"Scene.fx" ) );
  828.  
  829.     // If this fails, there should be debug output as to 
  830.     // they the .fx file failed to compile
  831.     V_RETURN( D3DXCreateEffectFromFile( pd3dDevice, str, NULL, NULL, dwShaderFlags, 
  832.                                         NULL, &g_pEffect, NULL ) );
  833.  
  834.     // Initialize the postprocess objects
  835.     for( int i = 0; i < PPCOUNT; ++i )
  836.     {
  837.         hr = g_aPostProcess[i].Init( pd3dDevice, dwShaderFlags, g_aszFxFile[i] );
  838.         if( FAILED( hr ) )
  839.             return hr;
  840.     }
  841.  
  842.     // Obtain the technique handles
  843.     switch( g_nPasses )
  844.     {
  845.         case 1:
  846.             g_hTRenderScene = g_pEffect->GetTechniqueByName( "RenderScene" );
  847.             g_hTRenderEnvMapScene = g_pEffect->GetTechniqueByName( "RenderEnvMapScene" );
  848.             g_hTRenderSkyBox = g_pEffect->GetTechniqueByName( "RenderSkyBox" );
  849.             break;
  850.         case 2:
  851.             g_hTRenderScene = g_pEffect->GetTechniqueByName( "RenderSceneTwoPasses" );
  852.             g_hTRenderEnvMapScene = g_pEffect->GetTechniqueByName( "RenderEnvMapSceneTwoPasses" );
  853.             g_hTRenderSkyBox = g_pEffect->GetTechniqueByName( "RenderSkyBoxTwoPasses" );
  854.             break;
  855.         case 3:
  856.             g_hTRenderScene = g_pEffect->GetTechniqueByName( "RenderSceneThreePasses" );
  857.             g_hTRenderEnvMapScene = g_pEffect->GetTechniqueByName( "RenderEnvMapSceneThreePasses" );
  858.             g_hTRenderSkyBox = g_pEffect->GetTechniqueByName( "RenderSkyBoxThreePasses" );
  859.             break;
  860.     }
  861.     g_hTRenderNoLight = g_pEffect->GetTechniqueByName( "RenderNoLight" );
  862.  
  863.     // Create vertex declaration for scene
  864.     if( FAILED( hr = pd3dDevice->CreateVertexDeclaration( MESHVERT::Decl, &g_pVertDecl ) ) )
  865.     {
  866.         return hr;
  867.     }
  868.  
  869.     // Create vertex declaration for skybox
  870.     if( FAILED( hr = pd3dDevice->CreateVertexDeclaration( SKYBOXVERT::Decl, &g_pSkyBoxDecl ) ) )
  871.     {
  872.         return hr;
  873.     }
  874.  
  875.     // Create vertex declaration for post-process
  876.     if( FAILED( hr = pd3dDevice->CreateVertexDeclaration( PPVERT::Decl, &g_pVertDeclPP ) ) )
  877.     {
  878.         return hr;
  879.     }
  880.  
  881.     // Load the meshes
  882.     if( FAILED( g_SceneMesh[0].Create( pd3dDevice, L"dwarf\\dwarf.x" ) ) )
  883.         return DXUTERR_MEDIANOTFOUND;
  884.     g_SceneMesh[0].SetVertexDecl( pd3dDevice, MESHVERT::Decl );
  885.     if( FAILED( g_SceneMesh[1].Create( pd3dDevice, L"misc\\skullocc.x" ) ) )
  886.         return DXUTERR_MEDIANOTFOUND;
  887.     g_SceneMesh[1].SetVertexDecl( pd3dDevice, MESHVERT::Decl );
  888.     if( FAILED( g_Skybox.Create( pd3dDevice, L"alley_skybox.x" ) ) )
  889.         return DXUTERR_MEDIANOTFOUND;
  890.     g_Skybox.SetVertexDecl( pd3dDevice, SKYBOXVERT::Decl );
  891.  
  892.     // Initialize the mesh's world matrix
  893.     ComputeMeshWorldMatrix( g_SceneMesh[g_nScene].GetSysMemMesh() );
  894.  
  895.     return S_OK;
  896. }
  897.  
  898.  
  899. //--------------------------------------------------------------------------------------
  900. // This callback function will be called immediately after the Direct3D device has been 
  901. // reset, which will happen after a lost device scenario. This is the best location to 
  902. // create D3DPOOL_DEFAULT resources since these resources need to be reloaded whenever 
  903. // the device is lost. Resources created here should be released in the OnLostDevice 
  904. // callback. 
  905. //--------------------------------------------------------------------------------------
  906. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, 
  907.                                 const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  908. {
  909.     HRESULT hr;
  910.  
  911.     if( g_pFont )
  912.         V_RETURN( g_pFont->OnResetDevice() );
  913.     if( g_pEffect )
  914.         V_RETURN( g_pEffect->OnResetDevice() );
  915.  
  916.     for( int p = 0; p < PPCOUNT; ++p )
  917.         V_RETURN( g_aPostProcess[p].OnResetDevice( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height ) );
  918.  
  919.     // Create a sprite to help batch calls when drawing many lines of text
  920.     V_RETURN( D3DXCreateSprite( pd3dDevice, &g_pTextSprite ) );
  921.  
  922.     // Setup the camera's projection parameters
  923.     float fAspectRatio = pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height;
  924.     g_Camera.SetProjParams( D3DX_PI/4, fAspectRatio, 0.1f, 1000.0f );
  925.     g_pEffect->SetMatrix( "g_mProj", g_Camera.GetProjMatrix() );
  926.     g_Camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
  927.  
  928.     g_SceneMesh[0].RestoreDeviceObjects( pd3dDevice );
  929.     g_SceneMesh[1].RestoreDeviceObjects( pd3dDevice );
  930.     g_Skybox.RestoreDeviceObjects( pd3dDevice );
  931.  
  932.     // Create scene save texture
  933.     for( int i = 0; i < RT_COUNT; ++i )
  934.     {
  935.         V_RETURN( pd3dDevice->CreateTexture( pBackBufferSurfaceDesc->Width,
  936.                                              pBackBufferSurfaceDesc->Height,
  937.                                              1,
  938.                                              D3DUSAGE_RENDERTARGET,
  939.                                              g_TexFormat,
  940.                                              D3DPOOL_DEFAULT,
  941.                                              &g_pSceneSave[i],
  942.                                              NULL ) );
  943.  
  944.         // Create the textures for this render target chains
  945.         IDirect3DTexture9 *pRT[2];
  946.         ZeroMemory( pRT, sizeof(pRT) );
  947.         for( int t = 0; t < 2; ++t )
  948.         {
  949.             V_RETURN( pd3dDevice->CreateTexture( pBackBufferSurfaceDesc->Width,
  950.                                                  pBackBufferSurfaceDesc->Height,
  951.                                                  1,
  952.                                                  D3DUSAGE_RENDERTARGET,
  953.                                                  D3DFMT_A8R8G8B8,
  954.                                                  D3DPOOL_DEFAULT,
  955.                                                  &pRT[t],
  956.                                                  NULL ) );
  957.         }
  958.         g_RTChain[i].Init( pRT );
  959.         SAFE_RELEASE( pRT[0] );
  960.         SAFE_RELEASE( pRT[1] );
  961.     }
  962.  
  963.     // Create the environment mapping texture
  964.     WCHAR str[MAX_PATH];
  965.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"Light Probes\\uffizi_cross.dds" ) );
  966.     if( FAILED( D3DXCreateCubeTextureFromFile( pd3dDevice, str, &g_pEnvTex ) ) )
  967.         return DXUTERR_MEDIANOTFOUND;
  968.  
  969.     // Initialize the render target table based on how many simultaneous RTs
  970.     // the card can support.
  971.     IDirect3DSurface9* pSurf;
  972.     switch( g_nPasses )
  973.     {
  974.         case 1:
  975.             g_pSceneSave[0]->GetSurfaceLevel( 0, &pSurf );
  976.             g_aRtTable[0].pRT[0] = pSurf;
  977.             g_pSceneSave[1]->GetSurfaceLevel( 0, &pSurf );
  978.             g_aRtTable[0].pRT[1] = pSurf;
  979.             g_pSceneSave[2]->GetSurfaceLevel( 0, &pSurf );
  980.             g_aRtTable[0].pRT[2] = pSurf;
  981.             // Passes 1 and 2 are not used
  982.             g_aRtTable[1].pRT[0] = NULL;
  983.             g_aRtTable[1].pRT[1] = NULL;
  984.             g_aRtTable[1].pRT[2] = NULL;
  985.             g_aRtTable[2].pRT[0] = NULL;
  986.             g_aRtTable[2].pRT[1] = NULL;
  987.             g_aRtTable[2].pRT[2] = NULL;
  988.             break;
  989.         case 2:
  990.             g_pSceneSave[0]->GetSurfaceLevel( 0, &pSurf );
  991.             g_aRtTable[0].pRT[0] = pSurf;
  992.             g_pSceneSave[1]->GetSurfaceLevel( 0, &pSurf );
  993.             g_aRtTable[0].pRT[1] = pSurf;
  994.             g_aRtTable[0].pRT[2] = NULL;  // RT 2 of pass 0 not used
  995.             g_pSceneSave[2]->GetSurfaceLevel( 0, &pSurf );
  996.             g_aRtTable[1].pRT[0] = pSurf;
  997.             // RT 1 & 2 of pass 1 not used
  998.             g_aRtTable[1].pRT[1] = NULL;
  999.             g_aRtTable[1].pRT[2] = NULL;
  1000.             // Pass 2 not used
  1001.             g_aRtTable[2].pRT[0] = NULL;
  1002.             g_aRtTable[2].pRT[1] = NULL;
  1003.             g_aRtTable[2].pRT[2] = NULL;
  1004.             break;
  1005.         case 3:
  1006.             g_pSceneSave[0]->GetSurfaceLevel( 0, &pSurf );
  1007.             g_aRtTable[0].pRT[0] = pSurf;
  1008.             // RT 1 & 2 of pass 0 not used
  1009.             g_aRtTable[0].pRT[1] = NULL;
  1010.             g_aRtTable[0].pRT[2] = NULL;
  1011.             g_pSceneSave[1]->GetSurfaceLevel( 0, &pSurf );
  1012.             g_aRtTable[1].pRT[0] = pSurf;
  1013.             // RT 1 & 2 of pass 1 not used
  1014.             g_aRtTable[1].pRT[1] = NULL;
  1015.             g_aRtTable[1].pRT[2] = NULL;
  1016.             g_pSceneSave[2]->GetSurfaceLevel( 0, &pSurf );
  1017.             g_aRtTable[2].pRT[0] = pSurf;
  1018.             // RT 1 & 2 of pass 2 not used
  1019.             g_aRtTable[2].pRT[1] = NULL;
  1020.             g_aRtTable[2].pRT[2] = NULL;
  1021.             break;
  1022.     }
  1023.  
  1024.     g_HUD.SetLocation( 0, 100 );
  1025.     g_HUD.SetSize( 170, 170 );
  1026.     g_SampleUI.SetLocation( pBackBufferSurfaceDesc->Width-225, 5 );
  1027.     g_SampleUI.SetSize( 220, 470 );
  1028.  
  1029.     return S_OK;
  1030. }
  1031.  
  1032.  
  1033. //--------------------------------------------------------------------------------------
  1034. // This callback function will be called once at the beginning of every frame. This is the
  1035. // best location for your application to handle updates to the scene, but is not 
  1036. // intended to contain actual rendering calls, which should instead be placed in the 
  1037. // OnFrameRender callback.  
  1038. //--------------------------------------------------------------------------------------
  1039. void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  1040. {
  1041.     // Update the camera's position based on user input 
  1042.     g_Camera.FrameMove( fElapsedTime );
  1043. }
  1044.  
  1045.  
  1046. //--------------------------------------------------------------------------------------
  1047. // Name: PerformSinglePostProcess()
  1048. // Desc: Perform post-process by setting the previous render target as a
  1049. //       source texture and rendering a quad with the post-process technique
  1050. //       set.
  1051. //       This method changes render target without saving any. The caller
  1052. //       should ensure that the default render target is saved before calling
  1053. //       this.
  1054. //       When this method is invoked, m_dwNextTarget is the index of the
  1055. //       rendertarget of this post-process.  1 - m_dwNextTarget is the index
  1056. //       of the source of this post-process.
  1057. HRESULT PerformSinglePostProcess( IDirect3DDevice9 *pd3dDevice,
  1058.                                   CPostProcess &PP,
  1059.                                   CPProcInstance &Inst,
  1060.                                   IDirect3DVertexBuffer9 *pVB,
  1061.                                   PPVERT *aQuad,
  1062.                                   float &fExtentX,
  1063.                                   float &fExtentY )
  1064. {
  1065.     HRESULT hr;
  1066.  
  1067.     //
  1068.     // The post-process effect may require that a copy of the
  1069.     // originally rendered scene be available for use, so
  1070.     // we initialize them here.
  1071.     //
  1072.  
  1073.     for( int i = 0; i < RT_COUNT; ++i )
  1074.         PP.m_pEffect->SetTexture( PP.m_hTexScene[i], g_pSceneSave[i] );
  1075.  
  1076.     //
  1077.     // If there are any parameters, initialize them here.
  1078.     //
  1079.  
  1080.     for( int i = 0; i < NUM_PARAMS; ++i )
  1081.         if( PP.m_ahParam[i] )
  1082.             PP.m_pEffect->SetVector( PP.m_ahParam[i], &Inst.m_avParam[i] );
  1083.  
  1084.     // Render the quad
  1085.     if( SUCCEEDED( pd3dDevice->BeginScene() ) )
  1086.     {
  1087.         PP.m_pEffect->SetTechnique( "PostProcess" );
  1088.  
  1089.         // Set the vertex declaration
  1090.         pd3dDevice->SetVertexDeclaration( g_pVertDeclPP );
  1091.  
  1092.         // Draw the quad
  1093.         UINT cPasses, p;
  1094.         PP.m_pEffect->Begin( &cPasses, 0 );
  1095.         for( p = 0; p < cPasses; ++p )
  1096.         {
  1097.             bool bUpdateVB = false;  // Inidicates whether the vertex buffer
  1098.                                      // needs update for this pass.
  1099.  
  1100.             //
  1101.             // If the extents has been modified, the texture coordinates
  1102.             // in the quad need to be updated.
  1103.             //
  1104.  
  1105.             if( aQuad[1].tu != fExtentX )
  1106.             {
  1107.                 aQuad[1].tu = aQuad[3].tu = fExtentX;
  1108.                 bUpdateVB = true;
  1109.             }
  1110.             if( aQuad[2].tv != fExtentY )
  1111.             {
  1112.                 aQuad[2].tv = aQuad[3].tv = fExtentY;
  1113.                 bUpdateVB = true;
  1114.             }
  1115.  
  1116.             //
  1117.             // Check if the pass has annotation for extent info.  Update
  1118.             // fScaleX and fScaleY if it does.  Otherwise, default to 1.0f.
  1119.             //
  1120.  
  1121.             float fScaleX = 1.0f, fScaleY = 1.0f;
  1122.             D3DXHANDLE hPass = PP.m_pEffect->GetPass( PP.m_hTPostProcess, p );
  1123.             D3DXHANDLE hExtentScaleX = PP.m_pEffect->GetAnnotationByName( hPass, "fScaleX" );
  1124.             if( hExtentScaleX )
  1125.                 PP.m_pEffect->GetFloat( hExtentScaleX, &fScaleX );
  1126.             D3DXHANDLE hExtentScaleY = PP.m_pEffect->GetAnnotationByName( hPass, "fScaleY" );
  1127.             if( hExtentScaleY )
  1128.                 PP.m_pEffect->GetFloat( hExtentScaleY, &fScaleY );
  1129.  
  1130.             //
  1131.             // Now modify the quad according to the scaling values specified for
  1132.             // this pass
  1133.             //
  1134.             if( fScaleX != 1.0f )
  1135.             {
  1136.                 aQuad[1].x = (aQuad[1].x + 0.5f) * fScaleX - 0.5f;
  1137.                 aQuad[3].x = (aQuad[3].x + 0.5f) * fScaleX - 0.5f;
  1138.                 bUpdateVB = true;
  1139.             }
  1140.             if( fScaleY != 1.0f )
  1141.             {
  1142.                 aQuad[2].y = (aQuad[2].y + 0.5f) * fScaleY - 0.5f;
  1143.                 aQuad[3].y = (aQuad[3].y + 0.5f) * fScaleY - 0.5f;
  1144.                 bUpdateVB = true;
  1145.             }
  1146.  
  1147.             if( bUpdateVB )
  1148.             {
  1149.                 LPVOID pVBData;
  1150.                 // Scaling requires updating the vertex buffer.
  1151.                 if( SUCCEEDED( pVB->Lock( 0, 0, &pVBData, D3DLOCK_DISCARD ) ) )
  1152.                 {
  1153.                     CopyMemory( pVBData, aQuad, 4 * sizeof(PPVERT) );
  1154.                     pVB->Unlock();
  1155.                 }
  1156.             }
  1157.             fExtentX *= fScaleX;
  1158.             fExtentY *= fScaleY;
  1159.  
  1160.             // Set up the textures and the render target
  1161.             //
  1162.             for( int i = 0; i < RT_COUNT; ++i )
  1163.             {
  1164.                 // If this is the very first post-process rendering,
  1165.                 // obtain the source textures from the scene.
  1166.                 // Otherwise, initialize the post-process source texture to
  1167.                 // the previous render target.
  1168.                 //
  1169.                 if( g_RTChain[i].m_bFirstRender )
  1170.                     PP.m_pEffect->SetTexture( PP.m_hTexSource[i], g_pSceneSave[i] );
  1171.                 else
  1172.                     PP.m_pEffect->SetTexture( PP.m_hTexSource[i], g_RTChain[i].GetNextSource() );
  1173.             }
  1174.  
  1175.             //
  1176.             // Set up the new render target
  1177.             //
  1178.             IDirect3DTexture9 *pTarget = g_RTChain[PP.m_nRenderTarget].GetNextTarget();
  1179.             IDirect3DSurface9 *pTexSurf;
  1180.             hr = pTarget->GetSurfaceLevel( 0, &pTexSurf );
  1181.             if( FAILED( hr ) )
  1182.                 return DXUT_ERR( L"GetSurfaceLevel", hr );
  1183.             pd3dDevice->SetRenderTarget( 0, pTexSurf );
  1184.             pTexSurf->Release();
  1185.             // We have output to this render target. Flag it.
  1186.             g_RTChain[PP.m_nRenderTarget].m_bFirstRender = false;
  1187.  
  1188.             //
  1189.             // Clear the render target
  1190.             //
  1191.             pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET,
  1192.                                0x00000000, 1.0f, 0L );
  1193.             //
  1194.             // Render
  1195.             //
  1196.             PP.m_pEffect->BeginPass( p );
  1197.             pd3dDevice->SetStreamSource( 0, pVB, 0, sizeof(PPVERT) );
  1198.             pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
  1199.             PP.m_pEffect->EndPass();
  1200.  
  1201.             // Update next rendertarget index
  1202.             g_RTChain[PP.m_nRenderTarget].Flip();
  1203.         }
  1204.         PP.m_pEffect->End();
  1205.  
  1206.         // End scene
  1207.         pd3dDevice->EndScene();
  1208.     }
  1209.  
  1210.     return S_OK;
  1211. }
  1212.  
  1213.  
  1214. //--------------------------------------------------------------------------------------
  1215. // PerformPostProcess()
  1216. // Perform all active post-processes in order.
  1217. HRESULT PerformPostProcess( IDirect3DDevice9 *pd3dDevice )
  1218. {
  1219.     HRESULT hr;
  1220.  
  1221.     //
  1222.     // Extents are used to control how much of the rendertarget is rendered
  1223.     // during postprocess. For example, with the extent of 0.5 and 0.5, only
  1224.     // the upper left quarter of the rendertarget will be rendered during
  1225.     // postprocess.
  1226.     //
  1227.     float fExtentX = 1.0f, fExtentY = 1.0f;
  1228.     const D3DSURFACE_DESC* pd3dsdBackBuffer = DXUTGetBackBufferSurfaceDesc();
  1229.  
  1230.     //
  1231.     // Set up our quad
  1232.     //
  1233.     PPVERT Quad[4] =
  1234.     {
  1235.         { -0.5f,                        -0.5f,                         1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f },
  1236.         { pd3dsdBackBuffer->Width-0.5f, -0.5,                          1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f },
  1237.         { -0.5,                         pd3dsdBackBuffer->Height-0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f },
  1238.         { pd3dsdBackBuffer->Width-0.5f, pd3dsdBackBuffer->Height-0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }
  1239.     };
  1240.  
  1241.     //
  1242.     // Create a vertex buffer out of the quad
  1243.     //
  1244.     IDirect3DVertexBuffer9 *pVB;
  1245.     hr = pd3dDevice->CreateVertexBuffer( sizeof(PPVERT) * 4,
  1246.                                          D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC,
  1247.                                          0,
  1248.                                          D3DPOOL_DEFAULT,
  1249.                                          &pVB,
  1250.                                          NULL );
  1251.     if( FAILED( hr ) )
  1252.         return DXUT_ERR( L"CreateVertexBuffer", hr );
  1253.  
  1254.     // Fill in the vertex buffer
  1255.     LPVOID pVBData;
  1256.     if( SUCCEEDED( pVB->Lock( 0, 0, &pVBData, D3DLOCK_DISCARD ) ) )
  1257.     {
  1258.         CopyMemory( pVBData, Quad, sizeof(Quad) );
  1259.         pVB->Unlock();
  1260.     }
  1261.  
  1262.     // Clear first-time render flags
  1263.     for( int i = 0; i < RT_COUNT; ++i )
  1264.         g_RTChain[i].m_bFirstRender = true;
  1265.  
  1266.     // Perform post processing
  1267.     CDXUTListBox *pListBox = g_SampleUI.GetListBox( IDC_ACTIVELIST );
  1268.     if( pListBox )
  1269.     {
  1270.         // The last (blank) item has special purpose so do not process it.
  1271.         for( int nEffIndex = 0; nEffIndex != pListBox->GetSize() - 1; ++nEffIndex )
  1272.         {
  1273.             DXUTListBoxItem *pItem = pListBox->GetItem( nEffIndex );
  1274.             if( pItem )
  1275.             {
  1276.                 CPProcInstance *pInstance = (CPProcInstance *)pItem->pData;
  1277.                 PerformSinglePostProcess( pd3dDevice,
  1278.                                         g_aPostProcess[pInstance->m_nFxIndex],
  1279.                                         *pInstance,
  1280.                                         pVB,
  1281.                                         Quad,
  1282.                                         fExtentX,
  1283.                                         fExtentY );
  1284.             }
  1285.         }
  1286.     }
  1287.  
  1288.     // Release the vertex buffer
  1289.     pVB->Release();
  1290.  
  1291.     return S_OK;
  1292. }
  1293.  
  1294.  
  1295. //--------------------------------------------------------------------------------------
  1296. // This callback function will be called at the end of every frame to perform all the 
  1297. // rendering calls for the scene, and it will also be called if the window needs to be 
  1298. // repainted. After this function has returned, the sample framework will call 
  1299. // IDirect3DDevice9::Present to display the contents of the next buffer in the swap chain
  1300. //--------------------------------------------------------------------------------------
  1301. void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  1302. {
  1303.     HRESULT hr;
  1304.     UINT cPass, p;
  1305.     LPD3DXMESH pMeshObj;
  1306.     D3DXMATRIXA16 mWorldView;
  1307.     
  1308.     // Clear the render target and the zbuffer 
  1309.     V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 45, 50, 170), 1.0f, 0) );
  1310.  
  1311.     // Save render target 0 so we can restore it later
  1312.     IDirect3DSurface9 *pOldRT;
  1313.     pd3dDevice->GetRenderTarget( 0, &pOldRT );
  1314.  
  1315.     // Render the scene
  1316.     if( SUCCEEDED( pd3dDevice->BeginScene() ) )
  1317.     {
  1318.         // Set the vertex declaration
  1319.         V( pd3dDevice->SetVertexDeclaration( g_pVertDecl ) );
  1320.  
  1321.         // Render the mesh
  1322.         D3DXMatrixMultiply( &mWorldView, &g_mMeshWorld, g_Camera.GetWorldMatrix() );
  1323.         D3DXMatrixMultiply( &mWorldView, &mWorldView, g_Camera.GetViewMatrix() );
  1324.         V( g_pEffect->SetMatrix( "g_mWorldView", &mWorldView ) );
  1325.         V( g_pEffect->SetTexture( "g_txEnvMap", g_pEnvTex ) );
  1326.         D3DXMATRIX mRevView = *g_Camera.GetViewMatrix();
  1327.         mRevView._41 = mRevView._42 = mRevView._43 = 0.0f;
  1328.         D3DXMatrixInverse( &mRevView, NULL, &mRevView );
  1329.         V( g_pEffect->SetMatrix( "g_mRevView", &mRevView ) );
  1330.  
  1331.         switch( g_nScene )
  1332.         {
  1333.             case 0:
  1334.                 V( g_pEffect->SetTechnique( g_hTRenderScene ) );
  1335.                 break;
  1336.             case 1:
  1337.                 V( g_pEffect->SetTechnique( g_hTRenderEnvMapScene ) );
  1338.                 break;
  1339.         }
  1340.  
  1341.         pMeshObj = g_SceneMesh[g_nScene].GetLocalMesh();
  1342.         V( g_pEffect->Begin( &cPass, 0 ) );
  1343.         for( p = 0; p < cPass; ++p )
  1344.         {
  1345.             // Set the render target(s) for this pass
  1346.             for( int rt = 0; rt < g_nRtUsed; ++rt )
  1347.                 V( pd3dDevice->SetRenderTarget( rt, g_aRtTable[p].pRT[rt] ) );
  1348.  
  1349.             V( g_pEffect->BeginPass( p ) );
  1350.  
  1351.             // Iterate through each subset and render with its texture
  1352.             for( DWORD m = 0; m < g_SceneMesh[g_nScene].m_dwNumMaterials; ++m )
  1353.             {
  1354.                 V( g_pEffect->SetTexture( "g_txScene", g_SceneMesh[g_nScene].m_pTextures[m] ) );
  1355.                 V( g_pEffect->CommitChanges() );
  1356.                 V( pMeshObj->DrawSubset( m ) );
  1357.             }
  1358.  
  1359.             V( g_pEffect->EndPass() );
  1360.         }
  1361.         V( g_pEffect->End() );
  1362.  
  1363.         // Render the skybox as if the camera is at center
  1364.         V( g_pEffect->SetTechnique( g_hTRenderSkyBox ) );
  1365.         V( pd3dDevice->SetVertexDeclaration( g_pSkyBoxDecl ) );
  1366.  
  1367.         D3DXMATRIXA16 mView = *g_Camera.GetViewMatrix();
  1368.         mView._41 = mView._42 = mView._43 = 0.0f;
  1369.  
  1370.         D3DXMatrixScaling( &mWorldView, 100.0f, 100.0f, 100.0f );
  1371.         D3DXMatrixMultiply( &mWorldView, &mWorldView, &mView );
  1372.         V( g_pEffect->SetMatrix( "g_mWorldView", &mWorldView ) );
  1373.  
  1374.         pMeshObj = g_Skybox.GetLocalMesh();
  1375.         V( g_pEffect->Begin( &cPass, 0 ) );
  1376.         for( p = 0; p < cPass; ++p )
  1377.         {
  1378.             // Set the render target(s) for this pass
  1379.             for( int rt = 0; rt < g_nRtUsed; ++rt )
  1380.                 V( pd3dDevice->SetRenderTarget( rt, g_aRtTable[p].pRT[rt] ) );
  1381.  
  1382.             V( g_pEffect->BeginPass( p ) );
  1383.  
  1384.             // Iterate through each subset and render with its texture
  1385.             for( DWORD m = 0; m < g_Skybox.m_dwNumMaterials; ++m )
  1386.             {
  1387.                 V( g_pEffect->SetTexture( "g_txScene", g_Skybox.m_pTextures[m] ) );
  1388.                 V( g_pEffect->CommitChanges() );
  1389.                 V( pMeshObj->DrawSubset( m ) );
  1390.             }
  1391.  
  1392.             V( g_pEffect->EndPass() );
  1393.         }
  1394.         V( g_pEffect->End() );
  1395.  
  1396.         V( pd3dDevice->EndScene() );
  1397.     }
  1398.  
  1399.     //
  1400.     // Swap the chains
  1401.     //
  1402.  
  1403.     for( int i = 0; i < RT_COUNT; ++i )
  1404.         g_RTChain[i].Flip();
  1405.  
  1406.     // Reset all render targets used besides RT 0
  1407.     for( i = 1; i < g_nRtUsed; ++i )
  1408.         V( pd3dDevice->SetRenderTarget( i, NULL ) );
  1409.  
  1410.     //
  1411.     // Perform post-processes
  1412.     //
  1413.  
  1414.     CDXUTListBox *pListBox = g_SampleUI.GetListBox( IDC_ACTIVELIST );
  1415.     bool bPerformPostProcess = g_bEnablePostProc && pListBox && ( pListBox->GetSize() > 1 );
  1416.     if( bPerformPostProcess )
  1417.         PerformPostProcess( pd3dDevice );
  1418.  
  1419.     // Restore old render target 0 (back buffer)
  1420.     V( pd3dDevice->SetRenderTarget( 0, pOldRT ) );
  1421.     SAFE_RELEASE( pOldRT );
  1422.  
  1423.     //
  1424.     // Get the final result image onto the backbuffer
  1425.     //
  1426.  
  1427.     const D3DSURFACE_DESC* pd3dsdBackBuffer = DXUTGetBackBufferSurfaceDesc();
  1428.     if( SUCCEEDED( pd3dDevice->BeginScene() ) )
  1429.     {
  1430.         // Render a screen-sized quad
  1431.         PPVERT quad[4] =
  1432.         {
  1433.             { -0.5f,                          -0.5f,                           0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f },
  1434.             { pd3dsdBackBuffer->Width - 0.5f, -0.5f,                           0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f },
  1435.             { -0.5f,                          pd3dsdBackBuffer->Height - 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f },
  1436.             { pd3dsdBackBuffer->Width - 0.5f, pd3dsdBackBuffer->Height - 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f }
  1437.         };
  1438.         IDirect3DTexture9 *pPrevTarget;
  1439.         pPrevTarget = ( bPerformPostProcess ) ? g_RTChain[0].GetPrevTarget() : g_pSceneSave[0];
  1440.  
  1441.         V( pd3dDevice->SetVertexDeclaration( g_pVertDeclPP ) );
  1442.         V( g_pEffect->SetTechnique( g_hTRenderNoLight ) );
  1443.         V( g_pEffect->SetTexture( "g_txScene", pPrevTarget ) );
  1444.         UINT cPasses;
  1445.         V( g_pEffect->Begin( &cPasses, 0 ) );
  1446.         for( p = 0; p < cPasses; ++p )
  1447.         {
  1448.             V( g_pEffect->BeginPass( p ) );
  1449.             V( pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, quad, sizeof(PPVERT) ) );
  1450.             V( g_pEffect->EndPass() );
  1451.         }
  1452.         V( g_pEffect->End() );
  1453.  
  1454.         // Render text
  1455.         RenderText();
  1456.  
  1457.         // Render dialogs
  1458.         V( g_HUD.OnRender( fElapsedTime ) );
  1459.         V( g_SampleUI.OnRender( fElapsedTime ) );
  1460.  
  1461.         V( pd3dDevice->EndScene() );
  1462.     }
  1463. }
  1464.  
  1465.  
  1466. //--------------------------------------------------------------------------------------
  1467. // Render the help and statistics text. This function uses the ID3DXFont interface for 
  1468. // efficient text rendering.
  1469. //--------------------------------------------------------------------------------------
  1470. void RenderText()
  1471. {
  1472.     // The helper object simply helps keep track of text position, and color
  1473.     // and then it calls pFont->DrawText( m_pSprite, strMsg, -1, &rc, DT_NOCLIP, m_clr );
  1474.     // If NULL is passed in as the sprite object, then it will work however the 
  1475.     // pFont->DrawText() will not be batched together.  Batching calls will improves performance.
  1476.     CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 15 );
  1477.     const D3DSURFACE_DESC* pd3dsdBackBuffer = DXUTGetBackBufferSurfaceDesc();
  1478.  
  1479.     // Output statistics
  1480.     txtHelper.Begin();
  1481.     txtHelper.SetInsertionPos( 5, 5 );
  1482.     txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
  1483.     txtHelper.DrawTextLine( DXUTGetFrameStats() );
  1484.     txtHelper.DrawTextLine( DXUTGetDeviceStats() );
  1485.  
  1486.     // If floating point rendertarget is not supported, display a warning
  1487.     // message to the user that some effects may not work correctly.
  1488.     if( D3DFMT_A16B16G16R16F != g_TexFormat )
  1489.     {
  1490.         txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f ) );
  1491.         txtHelper.SetInsertionPos( 5, 45 );
  1492.         txtHelper.DrawTextLine( L"Floating-point render target not supported\n"
  1493.                                 L"by the 3D device.  Some post-process effects\n"
  1494.                                 L"may not render correctly." );
  1495.     }
  1496.  
  1497.     // Draw help
  1498.     if( g_bShowHelp )
  1499.     {
  1500.         txtHelper.SetInsertionPos( 10, pd3dsdBackBuffer->Height-15*4 );
  1501.         txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 0.75f, 0.0f, 1.0f ) );
  1502.         txtHelper.DrawTextLine( L"Controls (F1 to hide):" );
  1503.  
  1504.         txtHelper.SetInsertionPos( 40, pd3dsdBackBuffer->Height-15*3 );
  1505.         txtHelper.DrawTextLine( L"Mesh Movement: Left drag mouse\n"
  1506.                                 L"Camera Movement: Right drag mouse\n" );
  1507.     }
  1508.     else
  1509.     {
  1510.         txtHelper.SetInsertionPos( 10, pd3dsdBackBuffer->Height-15*2 );
  1511.         txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
  1512.         txtHelper.DrawTextLine( L"Press F1 for help" );
  1513.     }
  1514.     txtHelper.End();
  1515. }
  1516.  
  1517.  
  1518. //--------------------------------------------------------------------------------------
  1519. // Before handling window messages, the sample framework passes incoming windows 
  1520. // messages to the application through this callback function. If the application sets 
  1521. // *pbNoFurtherProcessing to TRUE, then the sample framework will not process this message.
  1522. //--------------------------------------------------------------------------------------
  1523. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing )
  1524. {
  1525.     // Give the dialogs a chance to handle the message first
  1526.     *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
  1527.     if( *pbNoFurtherProcessing )
  1528.         return 0;
  1529.     *pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
  1530.     if( *pbNoFurtherProcessing )
  1531.         return 0;
  1532.  
  1533.     // Pass all remaining windows messages to camera so it can respond to user input
  1534.     g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
  1535.  
  1536.     return 0;
  1537. }
  1538.  
  1539.  
  1540. //--------------------------------------------------------------------------------------
  1541. // As a convenience, the sample framework inspects the incoming windows messages for
  1542. // keystroke messages and decodes the message parameters to pass relevant keyboard
  1543. // messages to the application.  The framework does not remove the underlying keystroke 
  1544. // messages, which are still passed to the application's MsgProc callback.
  1545. //--------------------------------------------------------------------------------------
  1546. void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown )
  1547. {
  1548.     if( bKeyDown )
  1549.     {
  1550.         switch( nChar )
  1551.         {
  1552.             case VK_F1: g_bShowHelp = !g_bShowHelp; break;
  1553.         }
  1554.     }
  1555. }
  1556.  
  1557.  
  1558. #define IN_FLOAT_CHARSET( c ) \
  1559.     ( (c) == L'-' || (c) == L'.' || ( (c) >= L'0' && (c) <= L'9' ) )
  1560.  
  1561. //--------------------------------------------------------------------------------------
  1562. // Parse a string that contains a list of floats separated by space, and store
  1563. // them in the array of float pointed to by pBuffer.
  1564. // Parses up to 4 floats.
  1565. void ParseFloatList( const WCHAR *pwszText, float *pBuffer )
  1566. {
  1567.     int nWritten = 0;  // Number of floats written
  1568.     const WCHAR *pToken, *pEnd;
  1569.     WCHAR wszToken[30];
  1570.  
  1571.     pToken = pwszText;
  1572.     while( nWritten < 4 && *pToken != L'\0' )
  1573.     {
  1574.         // Skip leading spaces
  1575.         while( *pToken == L' ' )
  1576.             ++pToken;
  1577.  
  1578.         // Locate the end of number
  1579.         pEnd = pToken;
  1580.         while( IN_FLOAT_CHARSET( *pEnd ) )
  1581.             ++pEnd;
  1582.  
  1583.         // Copy the token to our buffer
  1584.         int nTokenLen = min( sizeof(wszToken) / sizeof(wszToken[0]) - 1, int(pEnd - pToken) );
  1585.         wcsncpy( wszToken, pToken, nTokenLen );
  1586.         wszToken[nTokenLen] = L'\0';
  1587.         *pBuffer = (float)_wtof( wszToken );
  1588.         ++nWritten;
  1589.         ++pBuffer;
  1590.         pToken = pEnd;
  1591.     }
  1592. }
  1593.  
  1594.  
  1595. //--------------------------------------------------------------------------------------
  1596. // Inserts the postprocess effect identified by the index nEffectIndex into the
  1597. // active list.
  1598. void InsertEffect( int nEffectIndex )
  1599. {
  1600.     int nInsertPosition = g_SampleUI.GetListBox( IDC_ACTIVELIST )->GetSelectedIndex();
  1601.     if( nInsertPosition == -1 )
  1602.         nInsertPosition = g_SampleUI.GetListBox( IDC_ACTIVELIST )->GetSize() - 1;
  1603.  
  1604.     // Create a new CPProcInstance object and set it as the data field of the
  1605.     // newly inserted item.
  1606.     CPProcInstance *pNewInst = new CPProcInstance;
  1607.  
  1608.     if( pNewInst )
  1609.     {
  1610.         pNewInst->m_nFxIndex = nEffectIndex;
  1611.         ZeroMemory( pNewInst->m_avParam, sizeof( pNewInst->m_avParam ) );
  1612.         for( int p = 0; p < NUM_PARAMS; ++p )
  1613.             pNewInst->m_avParam[p] = g_aPostProcess[pNewInst->m_nFxIndex].m_avParamDef[p];
  1614.  
  1615.         g_SampleUI.GetListBox( IDC_ACTIVELIST )->InsertItem( nInsertPosition, g_aszPpDesc[nEffectIndex], pNewInst );
  1616.  
  1617.         // Set selection to the item after the inserted one.
  1618.         int nSelected = g_SampleUI.GetListBox( IDC_ACTIVELIST )->GetSelectedIndex();
  1619.         if( nSelected >= 0 )
  1620.             g_SampleUI.GetListBox( IDC_ACTIVELIST )->SelectItem( nSelected + 1 );
  1621.     }
  1622. }
  1623.  
  1624.  
  1625. //--------------------------------------------------------------------------------------
  1626. // Handles the GUI events
  1627. //--------------------------------------------------------------------------------------
  1628. void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl )
  1629. {
  1630.     switch( nControlID )
  1631.     {
  1632.         case IDC_TOGGLEFULLSCREEN: DXUTToggleFullScreen(); break;
  1633.         case IDC_TOGGLEREF:        DXUTToggleREF(); break;
  1634.         case IDC_CHANGEDEVICE:     DXUTSetShowSettingsDialog( !DXUTGetShowSettingsDialog() ); break;
  1635.         case IDC_SELECTSCENE:
  1636.         {
  1637.             DXUTComboBoxItem *pItem = ((CDXUTComboBox*)pControl)->GetSelectedItem();
  1638.             if( pItem )
  1639.             {
  1640.                 g_nScene = (int)(size_t)pItem->pData;
  1641.  
  1642.                 // Scene mesh has chanaged. Re-initialize the world matrix
  1643.                 // for the mesh.
  1644.                 ComputeMeshWorldMatrix( g_SceneMesh[g_nScene].GetSysMemMesh() );
  1645.             }
  1646.             break;
  1647.         }
  1648.         case IDC_AVAILABLELIST:
  1649.         {
  1650.             switch( nEvent )
  1651.             {
  1652.                 case EVENT_LISTBOX_ITEM_DBLCLK:
  1653.                 {
  1654.                     DXUTListBoxItem *pItem = ((CDXUTListBox*)pControl)->GetSelectedItem();
  1655.                     if( pItem )
  1656.                     {
  1657.                         // Inserts the selected effect in available list to the active list
  1658.                         // before its selected item.
  1659.  
  1660.                         InsertEffect( (int)(size_t)pItem->pData );
  1661.                     }
  1662.                     break;
  1663.                 }
  1664.             }
  1665.             break;
  1666.         }
  1667.  
  1668.         case IDC_ACTIVELIST:
  1669.         {
  1670.             switch( nEvent )
  1671.             {
  1672.                 case EVENT_LISTBOX_ITEM_DBLCLK:
  1673.                 {
  1674.                     int nSelected = ((CDXUTListBox*)pControl)->GetSelectedIndex();
  1675.  
  1676.                     // Do not remove the last (blank) item
  1677.                     if( nSelected != ((CDXUTListBox*)pControl)->GetSize() - 1 )
  1678.                     {
  1679.                         DXUTListBoxItem *pItem = ((CDXUTListBox*)pControl)->GetSelectedItem();
  1680.  
  1681.                         delete pItem->pData;
  1682.                         ((CDXUTListBox*)pControl)->RemoveItem( nSelected );
  1683.                     }
  1684.                     break;
  1685.                 }
  1686.                 case EVENT_LISTBOX_SELECTION:
  1687.                 {
  1688.                     // Selection changed in the active list.  Update the parameter
  1689.                     // controls.
  1690.  
  1691.                     int nSelected = ((CDXUTListBox*)pControl)->GetSelectedIndex();
  1692.  
  1693.                     if( nSelected >= 0 && nSelected < (int)((CDXUTListBox*)pControl)->GetSize() - 1 )
  1694.                     {
  1695.                         DXUTListBoxItem *pItem = ((CDXUTListBox*)pControl)->GetSelectedItem();
  1696.                         CPProcInstance *pInstance = (CPProcInstance *)pItem->pData;
  1697.                         CPostProcess &PP = g_aPostProcess[pInstance->m_nFxIndex];
  1698.  
  1699.                         if( pInstance && PP.m_awszParamName[0][0] != L'\0' )
  1700.                         {
  1701.                             g_SampleUI.GetStatic( IDC_PARAM0NAME )->SetText( PP.m_awszParamName[0] );
  1702.  
  1703.                             // Fill the editboxes with the parameter values
  1704.                             for( int p = 0; p < NUM_PARAMS; ++p )
  1705.                             {
  1706.                                 if( PP.m_awszParamName[p][0] != L'\0' )
  1707.                                 {
  1708.                                     // Enable the label and editbox for this parameter
  1709.                                     g_SampleUI.GetControl( IDC_PARAM0 + p )->SetEnabled( true );
  1710.                                     g_SampleUI.GetControl( IDC_PARAM0 + p )->SetVisible( true );
  1711.                                     g_SampleUI.GetControl( IDC_PARAM0NAME + p )->SetEnabled( true );
  1712.                                     g_SampleUI.GetControl( IDC_PARAM0NAME + p )->SetVisible( true );
  1713.  
  1714.                                     WCHAR wszParamText[512] = L"";
  1715.  
  1716.                                     for( int i = 0; i < PP.m_anParamSize[p]; ++i )
  1717.                                         swprintf( wszParamText + lstrlenW( wszParamText ), L"%.5f ", pInstance->m_avParam[p][i] );
  1718.                                     // Remove trailing space
  1719.                                     if( wszParamText[lstrlenW(wszParamText)-1] == L' ' )
  1720.                                         wszParamText[lstrlenW(wszParamText)-1] = L'\0';
  1721.                                     g_SampleUI.GetEditBox( IDC_PARAM0 + p )->SetText( wszParamText );
  1722.                                 }
  1723.                             }
  1724.                         } else
  1725.                         {
  1726.                             g_SampleUI.GetStatic( IDC_PARAM0NAME )->SetText( L"Selected effect has no parameters." );
  1727.  
  1728.                             // Disable the edit boxes and 2nd parameter static
  1729.                             g_SampleUI.GetControl( IDC_PARAM0 )->SetEnabled( false );
  1730.                             g_SampleUI.GetControl( IDC_PARAM0 )->SetVisible( false );
  1731.                             g_SampleUI.GetControl( IDC_PARAM1 )->SetEnabled( false );
  1732.                             g_SampleUI.GetControl( IDC_PARAM1 )->SetVisible( false );
  1733.                             g_SampleUI.GetControl( IDC_PARAM1NAME )->SetEnabled( false );
  1734.                             g_SampleUI.GetControl( IDC_PARAM1NAME )->SetVisible( false );
  1735.                         }
  1736.                     } else
  1737.                     {
  1738.                         g_SampleUI.GetStatic( IDC_PARAM0NAME )->SetText( L"Select an active effect to set its parameter." );
  1739.  
  1740.                         // Disable the edit boxes and 2nd parameter static
  1741.                         g_SampleUI.GetControl( IDC_PARAM0 )->SetEnabled( false );
  1742.                         g_SampleUI.GetControl( IDC_PARAM0 )->SetVisible( false );
  1743.                         g_SampleUI.GetControl( IDC_PARAM1 )->SetEnabled( false );
  1744.                         g_SampleUI.GetControl( IDC_PARAM1 )->SetVisible( false );
  1745.                         g_SampleUI.GetControl( IDC_PARAM1NAME )->SetEnabled( false );
  1746.                         g_SampleUI.GetControl( IDC_PARAM1NAME )->SetVisible( false );
  1747.                     }
  1748.  
  1749.                     break;
  1750.                 }
  1751.             }
  1752.             break;
  1753.         }
  1754.  
  1755.         case IDC_CLEAR:
  1756.         {
  1757.             ClearActiveList();
  1758.             break;
  1759.         }
  1760.  
  1761.         case IDC_MOVEUP:
  1762.         {
  1763.             CDXUTListBox *pListBox = g_SampleUI.GetListBox( IDC_ACTIVELIST );
  1764.             if( !pListBox )
  1765.                 break;
  1766.  
  1767.             int nSelected = pListBox->GetSelectedIndex();
  1768.             if( nSelected < 0 )
  1769.                 break;
  1770.  
  1771.             // Cannot move up the first item or the last (blank) item.
  1772.             if( nSelected != 0 && nSelected != pListBox->GetSize() - 1 )
  1773.             {
  1774.                 DXUTListBoxItem *pPrevItem = pListBox->GetItem( nSelected - 1 );
  1775.                 DXUTListBoxItem *pItem = pListBox->GetItem( nSelected );
  1776.                 DXUTListBoxItem Temp;
  1777.                 // Swap
  1778.                 Temp = *pItem;
  1779.                 *pItem = *pPrevItem;
  1780.                 *pPrevItem = Temp;
  1781.  
  1782.                 pListBox->SelectItem( nSelected - 1 );
  1783.             }
  1784.             break;
  1785.         }
  1786.  
  1787.         case IDC_MOVEDOWN:
  1788.         {
  1789.             CDXUTListBox *pListBox = g_SampleUI.GetListBox( IDC_ACTIVELIST );
  1790.             if( !pListBox )
  1791.                 break;
  1792.  
  1793.             int nSelected = pListBox->GetSelectedIndex();
  1794.             if( nSelected < 0 )
  1795.                 break;
  1796.  
  1797.             // Cannot move down either of the last two item.
  1798.             if( nSelected < pListBox->GetSize() - 2 )
  1799.             {
  1800.                 DXUTListBoxItem *pNextItem = pListBox->GetItem( nSelected + 1 );
  1801.                 DXUTListBoxItem *pItem = pListBox->GetItem( nSelected );
  1802.                 DXUTListBoxItem Temp;
  1803.                 // Swap
  1804.                 Temp = *pItem;
  1805.                 *pItem = *pNextItem;
  1806.                 *pNextItem = Temp;
  1807.  
  1808.                 pListBox->SelectItem( nSelected + 1 );
  1809.             }
  1810.             break;
  1811.         }
  1812.  
  1813.         case IDC_PARAM0:
  1814.         case IDC_PARAM1:
  1815.         {
  1816.             if( nEvent == EVENT_EDITBOX_CHANGE )
  1817.             {
  1818.                 int nParamIndex;
  1819.                 switch( nControlID )
  1820.                 {
  1821.                     case IDC_PARAM0: nParamIndex = 0; break;
  1822.                     case IDC_PARAM1: nParamIndex = 1; break;
  1823.                     default: return;
  1824.                 }
  1825.  
  1826.                 DXUTListBoxItem *pItem = g_SampleUI.GetListBox( IDC_ACTIVELIST )->GetSelectedItem();
  1827.                 CPProcInstance *pInstance = NULL;
  1828.                 if( pItem )
  1829.                     pInstance = (CPProcInstance *)pItem->pData;
  1830.  
  1831.                 if( pInstance )
  1832.                 {
  1833.                     D3DXVECTOR4 v;
  1834.                     ZeroMemory( &v, sizeof( v ) );
  1835.                     ParseFloatList( ((CDXUTEditBox *)pControl)->GetText(), (float*)&v );
  1836.  
  1837.                     // We parsed the values. Now save them in the instance data.
  1838.                     pInstance->m_avParam[nParamIndex] = v;
  1839.                 }
  1840.             }
  1841.             break;
  1842.         }
  1843.  
  1844.         case IDC_ENABLEPP:
  1845.         {
  1846.             g_bEnablePostProc = ((CDXUTCheckBox *)pControl)->GetChecked();
  1847.             break;
  1848.         }
  1849.  
  1850.         case IDC_PREBLUR:
  1851.         {
  1852.             // Clear the list
  1853.             ClearActiveList();
  1854.  
  1855.             // Insert effects
  1856.             InsertEffect( 9 );
  1857.             InsertEffect( 2 );
  1858.             InsertEffect( 3 );
  1859.             InsertEffect( 2 );
  1860.             InsertEffect( 3 );
  1861.             InsertEffect( 10 );
  1862.             break;
  1863.         }
  1864.  
  1865.         case IDC_PREBLOOM:
  1866.         {
  1867.             // Clear the list
  1868.             ClearActiveList();
  1869.  
  1870.             // Insert effects
  1871.             InsertEffect( 9 );
  1872.             InsertEffect( 9 );
  1873.             InsertEffect( 6 );
  1874.             InsertEffect( 4 );
  1875.             InsertEffect( 5 );
  1876.             InsertEffect( 4 );
  1877.             InsertEffect( 5 );
  1878.             InsertEffect( 10 );
  1879.             InsertEffect( 12 );
  1880.             break;
  1881.         }
  1882.  
  1883.         case IDC_PREDOF:
  1884.         {
  1885.             // Clear the list
  1886.             ClearActiveList();
  1887.  
  1888.             // Insert effects
  1889.             InsertEffect( 9 );
  1890.             InsertEffect( 2 );
  1891.             InsertEffect( 3 );
  1892.             InsertEffect( 2 );
  1893.             InsertEffect( 3 );
  1894.             InsertEffect( 10 );
  1895.             InsertEffect( 14 );
  1896.             break;
  1897.         }
  1898.  
  1899.         case IDC_PREEDGE:
  1900.         {
  1901.             // Clear the list
  1902.             ClearActiveList();
  1903.  
  1904.             // Insert effects
  1905.             InsertEffect( 13 );
  1906.             InsertEffect( 9 );
  1907.             InsertEffect( 4 );
  1908.             InsertEffect( 5 );
  1909.             InsertEffect( 12 );
  1910.             break;
  1911.         }
  1912.     }
  1913. }
  1914.  
  1915.  
  1916. //--------------------------------------------------------------------------------------
  1917. // This callback function will be called immediately after the Direct3D device has 
  1918. // entered a lost state and before IDirect3DDevice9::Reset is called. Resources created
  1919. // in the OnResetDevice callback should be released here, which generally includes all 
  1920. // D3DPOOL_DEFAULT resources. See the "Lost Devices" section of the documentation for 
  1921. // information about lost devices.
  1922. //--------------------------------------------------------------------------------------
  1923. void CALLBACK OnLostDevice()
  1924. {
  1925.     if( g_pFont )
  1926.         g_pFont->OnLostDevice();
  1927.     if( g_pEffect )
  1928.         g_pEffect->OnLostDevice();
  1929.     SAFE_RELEASE(g_pTextSprite);
  1930.  
  1931.     for( int p = 0; p < PPCOUNT; ++p )
  1932.         g_aPostProcess[p].OnLostDevice();
  1933.  
  1934.     // Release the scene save and render target textures
  1935.     for( int i = 0; i < RT_COUNT; ++i )
  1936.     {
  1937.         SAFE_RELEASE( g_pSceneSave[i] );
  1938.         g_RTChain[i].Cleanup();
  1939.     }
  1940.  
  1941.     g_SceneMesh[0].InvalidateDeviceObjects();
  1942.     g_SceneMesh[1].InvalidateDeviceObjects();
  1943.     g_Skybox.InvalidateDeviceObjects();
  1944.  
  1945.     // Release the RT table's references
  1946.     for( int p = 0; p < RT_COUNT; ++p )
  1947.         for( int rt = 0; rt < RT_COUNT; ++rt )
  1948.             SAFE_RELEASE( g_aRtTable[p].pRT[rt] );
  1949.  
  1950.     SAFE_RELEASE( g_pEnvTex );
  1951. }
  1952.  
  1953.  
  1954. //--------------------------------------------------------------------------------------
  1955. // This callback function will be called immediately after the Direct3D device has 
  1956. // been destroyed, which generally happens as a result of application termination or 
  1957. // windowed/full screen toggles. Resources created in the OnCreateDevice callback 
  1958. // should be released here, which generally includes all D3DPOOL_MANAGED resources. 
  1959. //--------------------------------------------------------------------------------------
  1960. void CALLBACK OnDestroyDevice()
  1961. {
  1962.     SAFE_RELEASE( g_pEffect );
  1963.     SAFE_RELEASE( g_pFont );
  1964.     SAFE_RELEASE( g_pVertDecl );
  1965.     SAFE_RELEASE( g_pSkyBoxDecl );
  1966.     SAFE_RELEASE( g_pVertDeclPP );
  1967.  
  1968.     g_SceneMesh[0].Destroy();
  1969.     g_SceneMesh[1].Destroy();
  1970.     g_Skybox.Destroy();
  1971.  
  1972.     for( int p = 0; p < PPCOUNT; ++p )
  1973.         g_aPostProcess[p].Cleanup();
  1974. }
  1975.